#extension GL_OES_standard_derivatives:enable
#define NUM_OCTAVES 5
precision mediump float;
varying float v_radius;
varying vec3 v_Normal;
varying vec3 v_position;
uniform vec3 u_PointLightPosition;
uniform vec3 u_DiffuseLight;
uniform vec3 u_AmbientLight;
uniform float u_time;
uniform vec2 u_Mouse;
uniform vec2 u_Resolution;


float mod289(float x){return x-floor(x*(1./289.))*289.;}
vec4 mod289(vec4 x){return x-floor(x*(1./289.))*289.;}
vec4 perm(vec4 x){return mod289(((x*34.)+1.)*x);}
mat3 rotation3dY(float angle){
	float s=sin(angle);
	float c=cos(angle);
	
	return mat3(
		c,0.,-s,
		0.,1.,0.,
		s,0.,c
	);
}
float noise(vec3 p){
	vec3 a=floor(p);
	vec3 d=p-a;
	d=d*d*(3.-2.*d);
	
	vec4 b=a.xxyy+vec4(0.,1.,0.,1.);
	vec4 k1=perm(b.xyxy);
	vec4 k2=perm(k1.xyxy+b.zzww);
	
	vec4 c=k2+a.zzzz;
	vec4 k3=perm(c);
	vec4 k4=perm(c+1.);
	
	vec4 o1=fract(k3*(1./41.));
	vec4 o2=fract(k4*(1./41.));
	
	vec4 o3=o2*d.z+o1*(1.-d.z);
	vec2 o4=o3.yw*d.x+o3.xz*(1.-d.x);
	
	return o4.y*d.y+o4.x*(1.-d.y);
}

float fbm(vec3 x){
	float v=0.;
	float a=.5;
	vec3 shift=vec3(100);
	for(int i=0;i<NUM_OCTAVES;++i){
		v+=a*noise(x);
		x=x*2.+shift;
		a*=.5;
	}
	return v;
}
mat3 inverse(mat3 m){
	float a00=m[0][0],a01=m[0][1],a02=m[0][2];
	float a10=m[1][0],a11=m[1][1],a12=m[1][2];
	float a20=m[2][0],a21=m[2][1],a22=m[2][2];
	
	float b01=a22*a11-a12*a21;
	float b11=-a22*a10+a12*a20;
	float b21=a21*a10-a11*a20;
	
	float det=a00*b01+a01*b11+a02*b21;
	
	return mat3(b01,(-a22*a01+a02*a21),(a12*a01-a02*a11),
	b11,(a22*a00-a02*a20),(-a12*a00+a02*a10),
	b21,(-a21*a00+a01*a20),(a11*a00-a01*a10))/det;
}
uniform float u_GradientMix;
uniform vec3 u_eyedirection;
varying mat3 v_rotation;
const float seed=.1;
uniform float u_Saturation;
uniform float u_Brightness;

const float lightStrength=1.;

struct Hue{
	float s;
	float e;
	float speed;
};

struct Light{
	vec3 position;
	vec3 color;
};
float createNoise(float level){
	vec3 wind=vec3(
		fbm(v_position*inverse(v_rotation)*level+u_time*.01+seed),
		fbm(v_position*inverse(v_rotation)*level-u_time*.02-seed),
		fbm(v_position*inverse(v_rotation)*level+u_time*.03+seed)
	);
	
	return fbm(v_position*inverse(v_rotation)*level+wind+seed);
}
vec3 hsv2rgb(vec3 c){
	vec4 K=vec4(1.,2./3.,1./3.,3.);
	vec3 p=abs(fract(c.xxx+K.xyz)*6.-K.www);
	return c.z*mix(K.xxx,clamp(p-K.xxx,0.,1.),c.y);
}
vec3 createColor(Hue h){
	vec3 hsv1=vec3(h.s+h.speed*u_time+seed,u_Saturation,u_Brightness);
	vec3 hsv2=vec3(h.e+h.speed*u_time+seed,u_Saturation,u_Brightness);
	
	vec3 rgb1=hsv2rgb(hsv1);
	vec3 rgb2=hsv2rgb(hsv2);
	
	float n=createNoise(u_GradientMix);
	
	return mix(rgb1,rgb2,n);
}
vec3 addLight(Light l){
	// get the surface directions
	vec3 dx=dFdx(v_position);
	vec3 dy=dFdy(v_position);
	
	// 获取最新的法线值
	vec3 newNormal=normalize(cross(dx,dy));
	
	// 法线混合
	vec3 N=mix(v_Normal,newNormal,.1);
	
	// 环境光
	float ambientStrength=.9;
	vec3 ambientColor=ambientStrength*l.color;
	
	// 平行光
	vec3 L=normalize(v_position-l.position);
	float diffuseScore=max(dot(L,N),0.);
	vec3 diffuseColor=diffuseScore*l.color;
	
	return ambientColor+diffuseColor;
}
vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d )
{
    return a + b*cos( 6.28318*(c*t+d) );
}

void main(void){
	// vec3 mouse =(u_Mouse.xy*2.- u_Resolution.xy)/min(u_Resolution.x,u_Resolution.y),5.);
	Light l=Light(
		vec3(0.,0.,5.)*inverse(v_rotation),
		vec3(lightStrength)
	);
	
	// Hue hue1=Hue(0.,.3,.1);
	// Hue hue2=Hue(.3,.6,.2);
	// Hue hue3=Hue(.7,.9,.3);
	
	// vec3 color1=createColor(hue1);
	// vec3 color2=createColor(hue2);
	// vec3 color3=createColor(hue3);

	vec3 color1=palette(u_time*0.01,vec3(0.5176, 0.6, 0.7255),	vec3(0.5, 0.5, 0.5)	,vec3(1.0, 1.0, 1.0)	,vec3(0.00, 0.33, 0.67));
	vec3 color2=palette(u_time*0.02,vec3(0.4745, 0.8, 0.5451)	,	vec3(0.5, 0.5, 0.5)	,vec3(1.0, 1.0, 1.0),	vec3(0.00, 0.10, 0.20));
	vec3 color3=palette(u_time*0.03,vec3(0.6392, 0.4, 0.8)	,	vec3(0.2, 0.4, 0.2)	,vec3(2.0, 1.0, 1.0)	,vec3(0.00, 0.25, 0.25));
	
	float mixer1=smoothstep(.35,.65,createNoise(u_GradientMix-.05));
	float mixer2=smoothstep(.35,.65,createNoise(u_GradientMix+.05));
	
	vec3 objectColor=mix(color1,color2,mixer1);
	objectColor=mix(objectColor,color3,mixer2);
	
	vec3 rgb=(addLight(l))*objectColor;
	
	gl_FragColor=vec4(rgb,1.);
}